﻿using Abp.AspNetCore;
using Abp.AspNetCore.Configuration;
using Abp.AspNetCore.SignalR;
using Abp.Configuration.Startup;
using Abp.Modules;
using Abp.Reflection.Extensions;
using Abp.Runtime.Caching.Redis;
using Abp.Zero.Configuration;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using NetCore.Authentication.JwtBearer;
using NetCore.Configuration;
using NetCore.EntityFrameworkCore;
using System;
using System.Text;

namespace NetCore
{
    [DependsOn(
         typeof(NetCoreApplicationModule),
         typeof(NetCoreEntityFrameworkModule),
         typeof(AbpAspNetCoreModule),
         typeof(AbpRedisCacheModule),
         typeof(AbpAspNetCoreSignalRModule)
     )]
    public class NetCoreWebCoreModule : AbpModule
    {
        private readonly IConfigurationRoot _appConfiguration;

        public NetCoreWebCoreModule(IHostingEnvironment env)
        {
            _appConfiguration = env.GetAppConfiguration();
        }

        public override void PreInitialize()
        {
            Configuration.DefaultNameOrConnectionString = _appConfiguration.GetConnectionString(
                NetCoreConsts.ConnectionStringName
            );

            // Use database for language management
            Configuration.Modules.Zero().LanguageManagement.EnableDbLocalization();


#if DEBUG
            //Abp 要包装异常，具体的操作是由转换器来决定的，Abp 实现了一个默认的转换器，叫做 DefaultErrorInfoConverter，在其内部，注入了
            //IAbpWebCommonModuleConfiguration 配置项，而用户可以通过配置该选项的 SendAllExceptionsToClients 属性来决定是否将异常输出给客户端。
            Configuration.Modules.AbpWebCommon().SendAllExceptionsToClients = true;//debug模式给客户端抛出错误消息
#endif
            ////用新的实现类替换系统默认接口的实现 示例
            //Configuration.ReplaceService<IPermissionChecker, PermissionChecker>();
            //Configuration.ReplaceService<IAuthorizationHelper, AuthorizationDatumHelper>();



            Configuration.Modules.AbpAspNetCore()
                 .CreateControllersForAppServices(
                     //Application的service生成的api/[AppName](配置文件中读) /[controller]/[Action]......
                     typeof(NetCoreApplicationModule).GetAssembly()
                 );
            #region Redis配置

            Configuration.Caching.UseRedis(options =>
            {
                options.ConnectionString = _appConfiguration["Abp:RedisCache:ConnectionStrings"];
                options.DatabaseId = Convert.ToInt32(_appConfiguration["Abp:RedisCache:DatabaseId"]);
            });
            Configuration.Caching.ConfigureAll(cache =>
            {
                //缓存默认过期时间设置为2h
                cache.DefaultSlidingExpireTime = TimeSpan.FromHours(2);
            });
            //用户个性签名验证码等缓存5分钟
            Configuration.Caching.Configure(NetCoreConsts.PersonalCaches, cache =>
            {
                cache.DefaultSlidingExpireTime = TimeSpan.FromMinutes(5);
            });
            ////企业员工Id与UserId集合 权限
            //Configuration.Caching.Configure(NetCoreConsts.StaffPermissionChecker, cache =>
            //{
            //    cache.DefaultSlidingExpireTime = TimeSpan.FromHours(2);
            //});

            ////用户未读消息 默认2h
            //Configuration.Caching.Configure(NetCoreConsts.UserUnReadNotify, cache =>
            //{
            //    cache.DefaultSlidingExpireTime = TimeSpan.FromHours(1);
            //});
            #endregion
            // For ABP Zero only 禁用审计日志
            Configuration.Auditing.IsEnabled = false; //关闭审计日志，默认为True
            Configuration.Auditing.IsEnabledForAnonymousUsers = false;   //未登录的用户是否记录日志，默认false
                                                                         //Configuration.Auditing.MvcControllers.IsEnabled = false;  //用于为MVC控制器开启或关闭审计。默认为true（MVC控制器审计单独配置）
                                                                         //Configuration.Auditing.MvcControllers.IsEnabledForChildActions = true;  //用于为子MVC action开启或关闭审计。默认为false。 
                                                                         //IsEnabled：用于完全启用/禁用审计系统。默认值：true。
                                                                         //IsEnabledForAnonymousUsers：如果设置为true，则为未登录系统的用户保存审核日志。默认值：false。
                                                                         //选择器：用于选择其他类以保存审核日志。
                                                                         //SaveReturnValues：用于启用/禁用以保存返回值。默认值：false。
                                                                         //IgnoredTypes：用于忽略已定义的类型。
                                                                         //选择器是一个谓词列表，用于选择保存审计日志的其他类型的类。选择器具有唯一名称和谓词。此列表中唯一的默认选择器用于选择应用
                                                                         //Selectors：选择其它类来保存审核日志
                                                                         //Configuration.Auditing.Selectors.Add(
                                                                         //    new NamedTypeSelector(
                                                                         //        "Abp.ApplicationServices",
                                                                         //        type => typeof (IApplicationService).IsAssignableFrom(type)
                                                                         //    )
                                                                         //);

            //Configuration.Modules.AbpWebCommon().MultiTenancy.DomainFormat = _appConfiguration["App:ServerRootAddress"] ?? "http://localhost:19999/";

            ////关闭实体历史记录日志
            //Configuration.EntityHistory.IsEnabled = false;

            ConfigureTokenAuth();
        }

        private void ConfigureTokenAuth()
        {
            IocManager.Register<TokenAuthConfiguration>();
            var tokenAuthConfig = IocManager.Resolve<TokenAuthConfiguration>();

            tokenAuthConfig.SecurityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(_appConfiguration["Authentication:JwtBearer:SecurityKey"]));
            tokenAuthConfig.Issuer = _appConfiguration["Authentication:JwtBearer:Issuer"];
            tokenAuthConfig.Audience = _appConfiguration["Authentication:JwtBearer:Audience"];
            tokenAuthConfig.SigningCredentials = new SigningCredentials(tokenAuthConfig.SecurityKey, SecurityAlgorithms.HmacSha256);
            tokenAuthConfig.Expiration = TimeSpan.FromDays(1);
        }

        public override void Initialize()
        {
            IocManager.RegisterAssemblyByConvention(typeof(NetCoreWebCoreModule).GetAssembly());
        }
    }
}
